package org.jwos.plugin.file.jcr.util;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.jcr.LoginException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.apache.jackrabbit.api.JackrabbitRepository;
import org.apache.log4j.Logger;


public class RepositorySessionFactory {
	
	protected static final String RepositorySessionKey = "RepositorySessionKey";
	
	protected static Logger logger = Logger.getLogger(RepositorySessionFactory.class);
	
	protected static String repHome = null;
	
	protected static JackrabbitRepositoryFactory factory = null;
		
	protected static Repository repository = null;	
	
	protected static final ThreadLocal threadLocal = new ThreadLocal();
	
	public static synchronized boolean buildRepositoryFactory(String serverWorkFolder) {
		logger.debug("build repository factory begin");
			
		boolean first = false;
		
		try {
			repHome = serverWorkFolder + "/repository";
			factory = new JackrabbitRepositoryFactory(repHome);
			
			File repDir = new File(repHome);
			if(!repDir.exists()) {
				logger.debug("build repository factory: create repository" + repHome + "begin");
				first = true;
				JackrabbitRepository jr = (JackrabbitRepository)factory.createRepository();
				jr.shutdown();
				logger.debug("build repository factory: create repository" + repHome + "end");
			} 
			
			File lockFile = new File(repHome+"/.lock");
			if(lockFile.exists()) {
				lockFile.delete();
			}
			
			repository = factory.getRepository();
		} catch (Exception e) {
			logger.debug("build repository factory error:"+e.getLocalizedMessage());
			e.printStackTrace();
		}
		
		logger.debug("build repository factory end:"+repHome); 
		
		return first;
	}
	
	public static synchronized void closeRepositoryFactory() {
		logger.debug("close repository factory begin");
		
		if(factory!=null) {
			factory.close();
		}
		
		logger.debug("close repository factory end:"+repHome); 
	}	
	
	public static synchronized Session openSession(String user,String password) 
			throws LoginException, RepositoryException {
		
		Map sessionMap = (Map)threadLocal.get();
		
		if(sessionMap==null) {
			sessionMap = new HashMap();
			threadLocal.set(sessionMap);
		}
		
		Session session = (Session)sessionMap.get(RepositorySessionFactory.RepositorySessionKey);
		if(session==null) {
			session = repository.login(new SimpleCredentials(user,(password==null ? "" : password).toCharArray()));
			sessionMap.put(RepositorySessionFactory.RepositorySessionKey,session);
		}		
		
		logger.debug("open repository session("+user+")");
		
		return session;		
	}
	
	public static synchronized void closeSession() {
		
		Map sessionMap = (HashMap)threadLocal.get();
		
		int count = 0;
		if(sessionMap!=null) {
			Session session = (Session)sessionMap.get(RepositorySessionFactory.RepositorySessionKey);
			if(session!=null) {
				count++;
				sessionMap.remove(RepositorySessionFactory.RepositorySessionKey);
				if(session.isLive()){
					logger.debug("close repository session("+session.getUserID()+")");
					session.logout();
				}
			}			
		}		
		
		threadLocal.set(null);
		logger.debug(count>0?"close repository session:"+count:"no session to close");
	}	
	
	public static synchronized Session currentSession() {
		
		try {
			Map sessionMap = (HashMap)threadLocal.get();		
			if(sessionMap!=null&&sessionMap.containsKey(RepositorySessionFactory.RepositorySessionKey)){
				return (Session)sessionMap.get(RepositorySessionFactory.RepositorySessionKey);
			} else {
				return openSession("yaj","");
			}
		} catch (LoginException e) {
			e.printStackTrace();
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
		
		return null;
	}	
}
